<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>canvas-demos</title>
    <style>
        * {
            margin: 0;
            padding: 0
        }
    </style>
</head>

<body>
<canvas id="cont">浏览器不支持</canvas>
<!--只能使用原生的js,如果让canvas左右居中使用display:block-->
<script>
    // 固定start获取画布
    const canvas = document.querySelector('#cont')
    // 获取画布上下文
    const ctx = canvas.getContext('2d')
    // 固定end

    const w = document.documentElement.clientWidth - 6
    const h = document.documentElement.clientHeight - 6
    canvas.width = w
    canvas.height = h

    function Ball(text) {
        this.x = randomNum(380) + 60
        this.y = randomNum(380) + 60
        this.r = randomNum(30) + 10
        this.color = `rgb(${parseInt((Math.random() * 256).toString())},${parseInt((Math.random() * 256).toString())},${parseInt((Math.random() * 256).toString())})`
        this.xSpeed = randomNum(3) + 2
        this.ySpeed = randomNum(3) + 1
        this.text = text
    }

    Ball.prototype.show = function () {
        this.run()
        // 画小球
        drawCircle(this.x, this.y, this.r, this.color)
        // 画文字
        drawText(this.text, this.x + this.r, this.y, this.color)
    }

    // 定义小球运动方法
    Ball.prototype.run = function () {
        if (this.x - this.r <= 0 || this.x + this.r >= w) {
            this.xSpeed = -this.xSpeed
        }
        this.x += this.xSpeed
        // 水平运动

        if (this.y - this.r <= 0 || this.y + this.r >= h) {
            this.ySpeed = -this.ySpeed
        }
        this.y += this.ySpeed
    }

    /**
     * 画出直线方法
     * @param x1
     * @param y1
     * @param x2
     * @param y2
     * @param color
     * @param width
     */

    function drawLine(x1, y1, x2, y2, color, width = 2) {
        // 画图开始:开启一条路径
        ctx.beginPath()
        // 确定起始点
        ctx.moveTo(x1, y1)
        // 确定结束点
        ctx.lineTo(x2, y2)
        // 在着色之前设置颜色和线宽
        ctx.strokeStyle = color
        ctx.lineWidth = width
        // 着色
        ctx.stroke()
        // 结束路径可以不关闭
        ctx.closePath()
    }

    /**
     *
     * @param text 正向思维好分析,逆向思维好编码
     * @param x
     * @param y
     * @param color 文字颜色
     */
    function drawText(text, x, y, color) {
        ctx.font = '20px 楷体'
        // "center" | "end" | "left" | "right" | "start";
        ctx.textAlign = 'left'
        ctx.textBaseline = 'middle'
        ctx.fillStyle = color
        ctx.fillText(text, x, y)
    }

    /**
     * 画实心小球
     * @param x
     * @param y
     * @param r
     * @param color
     */
    function drawCircle(x, y, r, color = '#000') {
        ctx.beginPath()
        ctx.arc(x, y, r, 0, Math.PI * 2)
        ctx.fillStyle = color
        ctx.fill()
    }

    /**
     * 获取随机值
     * @param inputNumber
     */
    function randomNum(inputNumber) {
        return Math.random() * inputNumber
    }

    const SHOW_TEXT = ['JAVA', 'SCALA', 'SPARK', 'PYTHON', 'SQL', 'ALICE']
    // 存放小球
    const ballArr = []
    for (let i = 0; i < 18; i++) {
        const ball = new Ball(SHOW_TEXT[i]);
        ballArr.push(ball)
    }

    // 让小球运动
    setInterval(function () {
        // 清楚画布
        ctx.clearRect(0, 0, w, h)
        const len = ballArr.length
        for (let i = 0; i < len; i++) {
            const ball = ballArr[i]
            ball.show()

            for (let j = 0; j < i; j++) {
                // 取出当前小球前面的小球
                const previousBall = ballArr[j]
                // 连线
                drawLine(ball.x, ball.y, previousBall.x, previousBall.y, ball.color)
            }
        }
    }, 5)

</script>
</body>
</html>
